package com.tron.sync.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tron.sync.entities.WpsOrg;
import com.tron.sync.entities.WpsUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;


/**
 * 更新用户，组织数据到WPS
 */
@Service
@Slf4j
public class WpsServiceImpl {

    @Value("${appId}")
    private String appId;
    @Value("${appSecret}")
    private String appSecret;
    @Value("${loginUrl}")
    private String loginUrl;
    @Value("${apiUrl}")
    private String apiUrl;

    RestTemplate restTemplate = new RestTemplate();

    @Autowired
    WpsUserService wpsUserService;

    @Autowired
    WpsOrgService wpsOrgService;


    /**
     * 获取部门列表
     *
     * @param syndaOrgId  第一级部门为ORG_ROOT
     * @return
     */
    public List<WpsOrg> getDeptList(String syndaOrgId) {
        List<WpsOrg> wpsOrgList = getWpsOrgListBySyndaOrgPid(syndaOrgId);
        return wpsOrgList;
    }

    /**
     * 创建部门
     *
     * @param wpsOrg orgName必传，wpsOrgPid必传, wpsOrgId必传
     * @return
     */
    public WpsOrg addDept(WpsOrg wpsOrg) {
        Assert.hasText(wpsOrg.getOrgName(), "创建部门错误，orgName不能为空");
        Assert.hasText(wpsOrg.getSyndaOrgId(), "创建部门错误，syndaOrgId不能为空");
        Assert.hasText(wpsOrg.getSyndaOrgPid(), "创建部门错误，syndaOrgPid不能为空");
        Assert.hasText(wpsOrg.getWpsOrgPid(),"创建部门错误,wpsOrgPid不能为空");
        WpsOrg byId = wpsOrgService.getById(wpsOrg.getSyndaOrgId());
        if (null != byId) {
            return byId;
        }
        try {
            //创建wps部门
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", wpsOrg.getOrgName());
            map.put("display_name", wpsOrg.getOrgName());
            HttpEntity<Object> httpEntity = new HttpEntity<>(map, getHttpHeaders());
            String Burl = apiUrl + "/api/v1/companies/1/depts/{1}/children";
            String postForObject = restTemplate.postForObject(Burl, httpEntity, String.class, wpsOrg.getWpsOrgPid());
            JSONObject jsonObject = JSONObject.parseObject(postForObject);
            String id = jsonObject.getString("id");
            wpsOrg.setWpsOrgId(id);
            wpsOrgService.save(wpsOrg);
            return wpsOrg;
        } catch (Exception e) {
            throw new RuntimeException("创建wps部门失败 error: " + e.getMessage());
        }
    }

    // 私有方法 删除空部门
    private String deleteDept(String syndaOrgId) {
        WpsOrg wpsOrg = getWpsOrgBySyndaOrgId(syndaOrgId);
        if (null == wpsOrg) {
            return syndaOrgId;
        }
        try {
            HashMap<String, Object> map = new HashMap<>();
            map.put("company", "1");
            map.put("dept", wpsOrg.getWpsOrgId());
            String url = apiUrl + "/api/v1/companies/{company}/depts/{dept}";
            HttpEntity<Object> httpEntity = new HttpEntity<>(getHttpHeaders());
            restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class, map);
            wpsOrgService.removeById(wpsOrg.getSyndaOrgId());
            return syndaOrgId;
        } catch (Exception e) {
            throw new RuntimeException("删除部门失败 error: " + e.getMessage());
        }

    }

    /**
     * 深度删除部门，会删除子部门及用户
     * @param syndaOrgId
     * @return
     */
    public String deepDeleteDept(String syndaOrgId) {
        Assert.hasText(syndaOrgId, "删除部门失败，syndaOrgId不能为空");
        //  删除部门下的用户
        deleteDeptUser(syndaOrgId);
        //  检查部门下是否有子部门
        List<WpsOrg> deptList = getDeptList(syndaOrgId);
        deptList.forEach(d -> {
            deepDeleteDept(d.getSyndaOrgId());
        });
        //  删除部门
        deleteDept(syndaOrgId);
        return "success";
    }

    /**
     * 跟新部门信息
     * @param wpsOrg
     * @return
     */
    public WpsOrg updateDept(WpsOrg wpsOrg) {
        Assert.hasText(wpsOrg.getSyndaOrgId(),"修改机构错误，syndaOrgId不能为空");
        Assert.hasText(wpsOrg.getSyndaOrgPid(),"修改机构错误，syndaOrgPid不能为空");
        Assert.hasText(wpsOrg.getOrgName(),"修改机构错误，orgName不能为空");
        WpsOrg bySyndaOrgId = getWpsOrgBySyndaOrgId(wpsOrg.getSyndaOrgId());
        WpsOrg bySyndaOrgPId = getWpsOrgBySyndaOrgId(wpsOrg.getSyndaOrgPid());
        if (null != bySyndaOrgId && null != bySyndaOrgPId) {
            wpsOrg.setWpsOrgId(bySyndaOrgId.getWpsOrgId());
            wpsOrg.setWpsOrgPid(bySyndaOrgPId.getWpsOrgId());
        }else {
            throw new RuntimeException("修改的机构或者父机构不存在");
        }
        try {
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", wpsOrg.getOrgName());
            map.put("display_name", wpsOrg.getOrgName());
            map.put("parent_id", wpsOrg.getWpsOrgPid());
            String url = apiUrl + "/api/v1/companies/1/depts/" +wpsOrg.getWpsOrgId();
            HttpEntity<Object> httpEntity = new HttpEntity<>(map,getHttpHeaders());
            RestTemplate restTemplate = getPatchRestTemplate();
            restTemplate.exchange(url, HttpMethod.PATCH, httpEntity, String.class);
            wpsOrgService.updateById(wpsOrg);
            return wpsOrg;
        } catch (Exception e) {
            throw new RuntimeException("修改部门失败 error: " + e.getMessage());
        }
    }

    /**
     * 获取用户信息
     * @param syndaUserId
     * @return
     */
    public WpsUser getUser(String syndaUserId) {
        Assert.hasText(syndaUserId,"获取用户信息失败，syndaUserId不能为空");
        WpsUser queryUser = getWpsUserBySyndaUserId(syndaUserId);
        return queryUser;
    }

    /**
     * 跟新用户信息
     * @param wpsUser
     * @return
     */
    public WpsUser updateUser(WpsUser wpsUser) {
        Assert.hasText(wpsUser.getUserName(),"修改用户失败，userName不能为空");
        Assert.hasText(wpsUser.getSyndaOrgId(),"修改用户失败，syndaOrgId不能为空");
        Assert.hasText(wpsUser.getSyndaUserId(),"修改用户失败，syndaUserId不能为空");
        WpsUser bySyndaUserId = getWpsUserBySyndaUserId(wpsUser.getSyndaUserId());
        WpsOrg bySyndaOrgId = getWpsOrgBySyndaOrgId(wpsUser.getSyndaOrgId());
        if (null != bySyndaOrgId && null != bySyndaUserId) {
            wpsUser.setWpsUserId(bySyndaUserId.getWpsUserId());
            wpsUser.setWpsOrgId(bySyndaOrgId.getWpsOrgId());
        }else {
            throw new RuntimeException("修改的用户不存在或部门不存在");
        }
        try {
            HashMap<String, Object> map = new HashMap<>();
            map.put("display_name", wpsUser.getUserName());
            map.put("preferred_dept_id", wpsUser.getWpsOrgId());
            String url = apiUrl + "/api/v1/companies/1/members/" +wpsUser.getWpsUserId();
            HttpEntity<Object> httpEntity = new HttpEntity<>(map,getHttpHeaders());
            RestTemplate restTemplate = getPatchRestTemplate();
            restTemplate.exchange(url, HttpMethod.PATCH, httpEntity, String.class);
            wpsUserService.updateById(wpsUser);
            return wpsUser;
        } catch (Exception e) {
            throw new RuntimeException("修改用户失败，error：" + e.getMessage());
        }
    }

    /**
     * 获取部门的成员列表
     * @param syndaOrgId
     * @return
     */
    public List<WpsUser> getDeptUser(String syndaOrgId) {
        Assert.hasText(syndaOrgId, "获取部门用户失败，syndaOrgId不能为空");
        List<WpsUser> bySyndaOrgId = getWpsUserListBySyndaOrgId(syndaOrgId);
        return bySyndaOrgId;
    }

    /**
     * 删除部门下的所有用户
     *
     * @param
     * @param syndaOrgId
     * @return
     */
    public String deleteDeptUser(String syndaOrgId) {
        List<WpsUser> deptUser = getDeptUser(syndaOrgId);
            deptUser.forEach(e -> {
                deleteUser(e.getSyndaUserId());
        });
        return deptUser.size()+"";
    }


    /**
     * 添加用户
     *
     * @param wpsUser
     * @return
     */
    public WpsUser addCompanyUser(WpsUser wpsUser) {
        Assert.hasText(wpsUser.getSyndaUserId(),"添加wps用户失败，syndaUserId不能为空");
        Assert.hasText(wpsUser.getUserName(), "添加wps用户失败,userName不能为空");
        Assert.hasText(wpsUser.getSyndaOrgId(), "添加用户失败，syndaOrgId不能为空");
        Assert.hasText(wpsUser.getCardNo(), "添加用户失败，cardNo不能为空");
        WpsUser bySyndaUserId = getWpsUserBySyndaUserId(wpsUser.getSyndaUserId());
        if (null != bySyndaUserId) {
            return bySyndaUserId;
        }
        WpsOrg wpsOrg = getWpsOrgBySyndaOrgId(wpsUser.getSyndaOrgId());
        if (null == wpsOrg) {
            throw new RuntimeException("添加用户失败，用户对应的机构还未同步到wps");
        }
        HashMap<String, Object> map = new HashMap<>();
        //账号
        map.put("unique_name", wpsUser.getCardNo());
        //用户密码包含字母最少8位
        map.put("password", "123!@#qweASD");
        //显示的用户名称
        map.put("display_name", wpsUser.getUserName());
        //在机构id
        map.put("preferred_dept_id", wpsOrg.getWpsOrgId());
        HttpEntity<Object> httpEntity = new HttpEntity<>(map, getHttpHeaders());
        try {
            String result = restTemplate.postForObject(apiUrl + "/api/v1/companies/1/members", httpEntity, String.class);
            JSONObject jsonObject = JSONObject.parseObject(result);
            JSONObject user = jsonObject.getJSONObject("user");
            String wpsUserId = user.getString("id");
            if (StringUtils.hasText(wpsUserId)) {
                wpsUser.setWpsUserId(wpsUserId);
                wpsUser.setWpsOrgId(wpsOrg.getWpsOrgId());
                wpsUserService.save(wpsUser);
                return wpsUser;
            } else {
                throw new RuntimeException(result + "用户信息：" + wpsUser);
            }
        } catch (Exception e) {
            throw new RuntimeException("创建wps用户失败 error: " + e.getMessage() + "用户信息：" + wpsUser);
        }
    }

    /**
     * 删除用户
     * @param syndaUserId
     * @return
     */
    public String deleteUser(String syndaUserId) {
        Assert.hasText(syndaUserId,"删除用户失败，syndaUserId不能为空");
        WpsUser wpsUser = getWpsUserBySyndaUserId(syndaUserId);
        if (null == wpsUser) {
            return syndaUserId;
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("company", "1");
        map.put("user", wpsUser.getWpsUserId());
        String url = apiUrl + "/api/v1/companies/{company}/members/{user}";
        HttpEntity<Object> httpEntity = new HttpEntity<>(getHttpHeaders());
        try {
            restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class, map);
            wpsUserService.removeById(syndaUserId);
        } catch (Exception e) {
            throw new RuntimeException("删除部门用户失败 error:" + e.getMessage());
        }
        return syndaUserId;
    }

    // 获取用户信息
    public WpsUser getWpsUserBySyndaUserId(String syndaUserId) {
        WpsUser queryUser = wpsUserService.getOne(Wrappers.<WpsUser>lambdaQuery().eq(StringUtils.hasText(syndaUserId), WpsUser::getSyndaUserId, syndaUserId));
        return queryUser;
    }

    // 获取用户列表
    public List<WpsUser> getWpsUserListBySyndaOrgId(String syndaOrgId) {
        List<WpsUser> wpsUsers = wpsUserService.list(Wrappers.<WpsUser>lambdaQuery().eq(WpsUser::getSyndaOrgId, syndaOrgId));
        return wpsUsers;
    }

    // 获取机构信息
    public WpsOrg getWpsOrgBySyndaOrgId(String syndaOrgId) {
        WpsOrg wpsOrg = wpsOrgService.getOne(Wrappers.<WpsOrg>lambdaQuery().eq(WpsOrg::getSyndaOrgId, syndaOrgId));
        return wpsOrg;
    }

    // 获取子机构列表
    public List<WpsOrg> getWpsOrgListBySyndaOrgPid(String syndaOrgPid) {
        List<WpsOrg> wpsOrgs = wpsOrgService.list(Wrappers.<WpsOrg>lambdaQuery().eq(WpsOrg::getSyndaOrgPid, syndaOrgPid));
        return wpsOrgs;
    }


    // 封装头部信息
    private HttpHeaders getHttpHeaders() {
        String token = getToken();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Authorization", token);
        return httpHeaders;
    }

    // patch 方法调用时使用该restTemplate
    private RestTemplate getPatchRestTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(5000);
        RestTemplate restTemplate = new RestTemplate(factory);
        return restTemplate;
    }

    /**
     * 获取操作部门，用户需要的token
     *
     * @return
     */
    public String getToken() {
        String type = "App.Company.Read App.Company.ReadWrite App.CompanyMembers.Read App.CompanyMembers.ReadWrite App.Depts.Read App.Depts.ReadWrite App.DeptMembers.Read App.DeptMembers.ReadWrite";
        String token = Base64.getEncoder().encodeToString((appId + ":" + appSecret).getBytes());
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Authorization", "Basic " + token);
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        LinkedMultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.put("grant_type", Arrays.asList("client_credentials"));
        multiValueMap.put("scope", Arrays.asList(type));
        HttpEntity<Object> httpEntity = new HttpEntity<>(multiValueMap, httpHeaders);
        try {
            String result = restTemplate.postForObject(apiUrl + "/oauth2/token", httpEntity, String.class);
            JSONObject jsonObject = JSONObject.parseObject(result);
            return "Bearer " + jsonObject.getString("access_token");
        } catch (Exception e) {
            log.info("获取wpsToken失败 =========================== 请求地址：{} appId: {} appSecret: {} error: {}", apiUrl, appId, appSecret, e.getMessage());
            throw new RuntimeException("获取token失败，请检查wps服务");
        }
    }

    /**
     * 调用登录方法获取cookie
     *
     * @param username
     * @param password
     * @return
     */
    public String login(String username, String password) {
        LinkedMultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.put("username", Arrays.asList(username));
        multiValueMap.put("password", Arrays.asList(password));
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<Object> httpEntity = new HttpEntity<>(multiValueMap, httpHeaders);
        String url = loginUrl + "/cts/v1/signin/password";
        log.info("请求路径：{}", url);
        ResponseEntity<String> postForEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        log.info("=============================={}", postForEntity.toString());
        HttpHeaders headers = postForEntity.getHeaders();
        log.info("=============================={}", headers.toSingleValueMap());
        List<String> strings = headers.get("Set-Cookie");
        return strings.get(0);
    }


}
